<!-- tab组件: <me-tabs v-model="tabIndex" :tabs="tabs" @change="tabChange"></me-tabs> -->
<template>
	<view class="me-tabs" :class="{ 'tabs-fixed': fixed }" :style="{ height: tabHeightVal }">
		<scroll-view v-if="tabs.length" :id="data.viewId" :scroll-left="data.scrollLeft" scroll-x scroll-with-animation
			:scroll-animation-duration="300">
			<view class="tabs-item tabs-scroll">
				<!-- tab -->
				<view class="tab-item"
					:style="{ paddingRight: gap + 'px', height: tabHeightVal, 'line-height': tabHeightVal }"
					v-for="(tab, i) in tabs" :class="{ active: data.current === i }" :key="i" @click="tabClick(i)">
					{{ getTabName(tab) }}
				</view>
				<!-- 下划线 -->
				<view class="tabs-line" :style="{ left: data.lineLeft }"></view>
			</view>
		</scroll-view>
	</view>
</template>

<script lang="ts" setup>
	import { reactive, computed, onMounted, nextTick } from 'vue'

	const emit = defineEmits(['update:modelValue'])

	interface Props {
		tabs ? : Array < any >
			nameKey ? : string
		modelValue ? : string | number
		fixed ? : boolean
		height ? : number
		gap ? : number
	}

	const props = withDefaults(defineProps < Props > (), {
		tabs: () => [],
		nameKey: 'name',
		value: 0,
		fixed: false,
		height: 64,
		gap: 30
	})

	interface dataProps {
		viewId: string
		scrollLeft: number
		itemsInfoList: Array < any >
			lineLeft: string
		current: number
		warpWidth: number
	}
	const data = reactive < dataProps > ({
		viewId: 'id' + Math.random().toString(36).substr(2, 16),
		scrollLeft: 0,
		itemsInfoList: [],
		lineLeft: '31px',
		current: 0,
		warpWidth: 0
	})

	const tabHeightPx = computed(() => {
		return uni.upx2px(props.height)
	})

	const tabHeightVal = computed(() => {
		return tabHeightPx.value + 'px'
	})

	onMounted(() => {
		nextTick(() => {
			const query = uni.createSelectorQuery()
			query
				.selectAll('.tab-item')
				.boundingClientRect((res: any) => {
					data.itemsInfoList = res.map((m: any) => m.width)
					tabClick(0)
				})
				.exec()
		})
	})

	function tabClick(i: number) {
		data.current = i
		if (props.value != i) {
			emit('update:modelValue', i)
		}
		if (data.itemsInfoList.length == 0) return 0
		let a = data.itemsInfoList.slice(0, data.current)
		let b = a.length > 0 ? a.reduce((pre: number, cur: number) => { return pre + cur }) : 0
		let c = (data.itemsInfoList[data.current] - props.gap) / 2

		data.lineLeft = 15 + b + c + 'px'
		scrollCenter()
	}
	async function scrollCenter() {
		if (!data.warpWidth) {
			// tabs容器的宽度
			let rect = await initWarpRect()
			data.warpWidth = rect ? rect.width : uni.getSystemInfoSync().windowWidth // 某些情况下取不到宽度,暂时取屏幕宽度
		}
		let tabLeft = parseInt(data.lineLeft) // 当前tab中心点到左边的距离
		let diff = tabLeft - data.warpWidth / 2 // 如果超过tabs容器的一半,则滚动差值
		data.scrollLeft = diff
	}

	function initWarpRect(): any {
		return new Promise(resolve => {
			setTimeout(() => {
				// 延时确保dom已渲染, 不使用$nextclick
				let query = uni.createSelectorQuery()
				query
					.select('#' + data.viewId)
					.boundingClientRect(res => {
						resolve(res)
					})
					.exec()
			}, 20)
		})
	}

	function getTabName(tab: any) {
		return typeof tab === 'object' ? tab[props.nameKey] : tab
	}
</script>

<style lang="scss" scoped>
	.me-tabs {
		position: relative;
		font-size: 32rpx;
		background-color: #fff;
		// border-bottom: 1rpx solid #eee;
		box-sizing: border-box;
		overflow-y: hidden;
		background-color: #fff;

		&.tabs-fixed {
			z-index: 990;
			position: fixed;
			top: var(--window-top);
			left: 0;
			width: 100%;
		}

		.tabs-item {
			position: relative;
			white-space: nowrap;
			box-sizing: border-box;
			padding: 0 30rpx;

			// padding-bottom: 30rpx; // 撑开高度,再配合me-tabs的overflow-y: hidden,以达到隐藏滚动条的目的
			.tab-item {
				position: relative;
				text-align: center;
				box-sizing: border-box;

				&.active {
					color: #fc4f75;
					// font-weight: 600;
					font-weight: bolder;
					font-size: 32rpx;
				}
			}

			// .tab-item:nth-child(1){
			//     margin-left: 30rpx;
			// }
		}

		// 平分的方式显示item
		.tabs-flex {
			display: flex;

			.tab-item {
				flex: 1;
			}
		}

		// 居左显示item,支持水平滑动
		.tabs-scroll {
			.tab-item {
				display: inline-block;
			}
		}

		// 选中tab的线
		.tabs-line {
			z-index: 1;
			position: absolute;
			bottom: 10rpx; // 至少与.tabs-item的padding-bottom一致,才能保证在底部边缘
			width: 50rpx;
			height: 6rpx;
			transform: translateX(-50%);
			border-radius: 4rpx;
			transition: left 0.3s;
			background: #fc4f75;
		}
	}
</style>
